%{
#include <ctype.h>
#include <string>
#include <vector>
#include <stack>
#include <stdio.h> 
#include <stdlib.h>
#include <conio.h>
#include <iostream>
#include <fstream>


// maximo de todas las constantes y id
#define MAX_STR           31
#define MAX_TAM_ID        31
#define MAX_HEX           4
#define MIN_INT           0
#define MAX_INT           65535
#define MIN_FLOAT         1.7e-38
#define MAX_FLOAT         3.4e38

#define MAX_IDS           100
#define MAX_TIPO          512 // maximo para almacernar un token
#define MAX_TOKEN         128 // maximo para almacernar un token

// errores
#define ERROR_RANGO_INT   -99
#define ERROR_RANGO_FLOAT -98
#define ERROR_STRING_MAX  -96
#define ERROR_STRING_CIERRE  -95
#define ERROR_COMEN_CIERRE -94
#define ERROR_CARACTER -93
#define ERROR_HEX -92
#define ERROR_TAM_ID -91
#define ERROR_NO_EXISTE_ID -90
#define ERROR_DECLARACION_DUPLICADA -89
#define ERROR_MAXIMO_TOKEN -88
#define ERROR_MAXIMO_TS -87
#define ERROR_INCOMPATIBILIDAD_TIPOS -86

// constantes para los tokens
#define QF                99      // estado final
#define CANT_SIMBOLOS     30      // cantidad de simbolos diferentes que hay que tener presente para el cambio de estado
#define CANT_TOKENS       51      // cantidad de tokens
#define CANT_TS           300     // cantidad de entradas de la tablas de simbolos
#define CANT_PR           22      // cantidad de palabras reservadas

// para el manejo de ids, tipos, y validaciones
#define CONTINUAR -2
#define ERROR_BUSCAR -1
#define OK 1

#define FINCOND    1001
#define FINTHEN    1002
#define FINELSE    1003
#define POSICION   1004
#define ETIQUETA   1006
#define VACIO      1007
#define CMP        1008
#define BI         1009
#define INIFOR     1010
#define FINFOR     1011
#define FINCONDFOR 1012
#define FINTRUE    1020
#define FINFALSE   1021
#define INIIF      1022
#define OPERADOR   1023
#define OPERANDO   1024
#define AUX        1025

using namespace std;
%}
%token ID CTE OP_ASIG SUMA
%token RESTA DIVISION MULTIPLIC
%token PARENABRE PARENCIERRA CORCHABRE CORCHCIERRA
%token LLAVEABRE LLAVECIERRA IGUAL MENOR MENORIGUAL DISTINTO
%token MAYOR MAYORIGUAL COMA CTE_REAL CTE_INT CTE_STR
%token DOSPUNTOS CONCAT GENERICO CTE_HEX WPRINT IF AND OR ELSE FOR ROF
%token CTOF KTOC CTOK FTOC BEGIN END VAR ENDVAR REAL STRING INTEGER
%token FI NOT
%%
programa : bloque_declaracion BEGIN sentencias END {generarASM(); printf("\n COMPILE SUCCESFUL WTF POSTA ????");}|
           {finDeclaracion=1;} BEGIN sentencias END {generarASM(); printf("\n COMPILE SUCCESFUL WTF POSTA ????");};

bloque_declaracion : VAR declaraciones ENDVAR {finDeclaracion=1;};

lista_ids : lista_ids COMA ID {cargarID($3);} |
            ID {cargarID($1);};

lista_tipos : lista_tipos COMA tipo |
              tipo;   

declaraciones : declaraciones CORCHABRE lista_ids CORCHCIERRA DOSPUNTOS CORCHABRE lista_tipos CORCHCIERRA {nuevaDeclaracion();} |
                CORCHABRE lista_ids CORCHCIERRA DOSPUNTOS CORCHABRE lista_tipos CORCHCIERRA {nuevaDeclaracion();};

tipo : REAL {cargarTipo(REAL);} | STRING {cargarTipo(STRING);} | INTEGER {cargarTipo(INTEGER);};

sentencias : sentencias sentencia | sentencia ;

sentencia : ciclo |
         asignacion | 
         decision |
         salida ; 

ciclo : FOR ID CTE_INT DOSPUNTOS CTE_INT {
           /* asignacion inicial implicita */
           generarPolaca(ID,$2,0);
		   generarPolaca(CTE,$3,0);
		   generarPolaca(OP_ASIG,0,0);
		   /* inicio de la condicion implicita */
		   generarPolaca(ETIQUETA,0,0);
		   generarPolaca(ID,$2,0);
		   generarPolaca(CTE,$5,0);
		   generarPolaca(CMP,0,0);
		   generarPolaca(VACIO,0,0); /* huevo para guardar donde termina */
		   generarPolaca(INIFOR,0,0);
		   
        } sentencias {
			/* suma la variable indice */
			generarPolaca(ID,$2,0);
			generarPolaca(ID,$2,0);
		    generarPolaca(CTE,guardarTablaSimbolos("1",CTE_INT,1,CTE),0);
			generarPolaca(SUMA,0,0);	
		    generarPolaca(OP_ASIG,0,0);		
		    generarPolaca(FINFOR,0,0);
		} ROF ;

asignacion : array_ids OP_ASIG expresion {generarPolaca(OP_ASIG,0,0);} |
             array_ids OP_ASIG string {generarPolaca(OP_ASIG,0,0);};
			 
array_ids : array_ids OP_ASIG ID {generarPolaca(ID,$3,0); /*generarPolaca(OP_ASIG,0,0);*/}|
            ID {generarPolaca(ID,$1,0);};

string : CTE_STR {generarPolaca(CTE_STR,$1,0);}|
         ID CONCAT CTE_STR {generarPolaca(ID,$1,0); generarPolaca(CTE_STR,$3,0); generarPolaca(CONCAT,0,0);}|
         CTE_STR CONCAT CTE_STR {generarPolaca(CTE_STR,$1,0); generarPolaca(CTE_STR,$3,0); generarPolaca(CONCAT,0,0);}|
         CTE_STR CONCAT ID  {generarPolaca(CTE_STR,$1,0); generarPolaca(ID,$3,0); generarPolaca(CONCAT,0,0);} |
         ID CONCAT ID {generarPolaca(ID,$1,0); generarPolaca(ID,$3,0); generarPolaca(CONCAT,0,0);};		 
		 
decision : IF PARENABRE condicion PARENCIERRA sentencias {generarPolaca(VACIO,0,0); generarPolaca(FINTRUE,0,0); generarPolaca(BI,0,0); generarPolaca(FINFALSE,0,0);} FI |
           IF PARENABRE condicion PARENCIERRA sentencias {generarPolaca(VACIO,0,0); generarPolaca(FINTRUE,0,0); generarPolaca(BI,0,0);} ELSE sentencias { generarPolaca(FINFALSE,0,0); } FI;
		   
condicion : condicion_simple |
            condicion_multiple; 

condicion_multiple : condicion_simple2 AND condicion_simple2 {generarPolaca(CMP,0,0); generarPolaca(INIIF,0,0); generarPolaca(VACIO,0,0); generarPolaca(AND,0,0);}|
                     condicion_simple2 OR condicion_simple2 {generarPolaca(CMP,0,0); generarPolaca(INIIF,0,0); generarPolaca(VACIO,0,0); generarPolaca(OR,0,0);}|
                     NOT condicion_simple2 {generarPolaca(CMP,0,0); generarPolaca(INIIF,0,0); generarPolaca(VACIO,0,0); generarPolaca(NOT,0,0);};

condicion_simple : expresion IGUAL expresion {generarPolaca(CMP,0,0); generarPolaca(INIIF,0,0); generarPolaca(VACIO,0,0); generarPolaca(IGUAL,0,0);}|
                   expresion MENOR expresion {generarPolaca(CMP,0,0); generarPolaca(INIIF,0,0); generarPolaca(VACIO,0,0); generarPolaca(MENOR,0,0);}|
                   expresion MENORIGUAL expresion {generarPolaca(CMP,0,0); generarPolaca(INIIF,0,0); generarPolaca(VACIO,0,0); generarPolaca(MENORIGUAL,0,0);}|
                   expresion MAYOR expresion {generarPolaca(CMP,0,0); generarPolaca(INIIF,0,0); generarPolaca(VACIO,0,0); generarPolaca(MAYOR,0,0);}|
                   expresion MAYORIGUAL expresion {generarPolaca(CMP,0,0); generarPolaca(INIIF,0,0); generarPolaca(VACIO,0,0); generarPolaca(MAYORIGUAL,0,0);}|
                   expresion DISTINTO expresion {generarPolaca(CMP,0,0); generarPolaca(INIIF,0,0); generarPolaca(VACIO,0,0); generarPolaca(DISTINTO,0,0);};
				   
condicion_simple2 : expresion IGUAL expresion {generarPolaca(IGUAL,0,0);}|
                   expresion MENOR expresion {generarPolaca(MENOR,0,0);}|
                   expresion MENORIGUAL expresion {generarPolaca(MENORIGUAL,0,0);}|
                   expresion MAYOR expresion {generarPolaca(MAYOR,0,0);}|
                   expresion MAYORIGUAL expresion {generarPolaca(MAYORIGUAL,0,0);}|
                   expresion DISTINTO expresion {generarPolaca(DISTINTO,0,0);};

expresion : expresion SUMA termino {generarPolaca(SUMA,0,0);}|
            expresion RESTA termino {generarPolaca(RESTA,0,0); }| 
            termino; 

termino : termino MULTIPLIC factor {generarPolaca(MULTIPLIC,0,0);}|
          termino DIVISION factor {generarPolaca(DIVISION,0,0);}|
          factor; 

factor : ID {generarPolaca(ID,$1,0);} |
         CTE_INT {generarPolaca(CTE,$1,0);} | 
         CTE_REAL {generarPolaca(CTE,$1,0);} | 
         {finDeclaracion=0;} cambio_base {finDeclaracion=1;} |
         funcion |
         PARENABRE expresion PARENCIERRA;

cambio_base : LLAVEABRE CTE_INT COMA CTE_INT LLAVECIERRA {if (validarCambioBase($2,$4,CTE) < 0 ) {exit(1);}}|
              LLAVEABRE ID COMA CTE_INT LLAVECIERRA {if (validarCambioBase($2,$4,ID) < 0 ) {exit(1);}} |
              LLAVEABRE CTE_HEX COMA CTE_INT LLAVECIERRA {if (validarCambioBase($2,$4,CTE) < 0 ) {exit(1);}} ;

funcion : FTOC PARENABRE expresion PARENCIERRA {generarPolaca(FTOC,0,$3);}|
          CTOF PARENABRE expresion PARENCIERRA {generarPolaca(CTOF,0,$3);}|
          KTOC PARENABRE expresion PARENCIERRA {generarPolaca(KTOC,0,$3);}|
          CTOK PARENABRE expresion PARENCIERRA {generarPolaca(CTOK,0,$3);};

salida : WPRINT PARENABRE string PARENCIERRA {generarPolaca(WPRINT,0,0);} |
         WPRINT PARENABRE expresion PARENCIERRA {generarPolaca(WPRINT,0,0);} ;
%%
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////GLOBALES PARA YYACC///////////////////////////////////////////
enum estadoDeclaracion {
        INICIAL, VALIDO, INVALIDO
};

struct decla_id {
   int id, tipo;
   enum estadoDeclaracion valido;
};

decla_id vec [MAX_IDS];
int id_decla = 0;
int tipo_decla = 0;
string filename; // para guardar el filename que se esta ejecutando
int cantidadCTE = 0;

int finDeclaracion = 0;

stack<int> vAnidamiento;
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
struct etiqueta {
	int posicion;
	char nombre[100];
};

struct etiqueta etiquetas[100];
int id_etiqueta = 0;

///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////


// =======================
// Estructuras para Polaca
// =======================
struct polaca {int valor; int indTS; int tipo;};
vector<polaca> vPolaca;
stack<int> vPila;


// ===================
// Estructuras para TS
// ===================

struct tabla{
    char nombre[MAX_TAM_ID+1];
    int tipo;
    char valor[MAX_TAM_ID+1];
    int longitud;
};
// ===================
FILE *archivo; // aca levanta el archivo fuente
FILE *archivoASM;
FILE *archivoPolaca;
int lineatxt = 1,coltxt = 1; // para saber donde ocurre el error
struct tabla tabla_simbolos [CANT_TS];

// Almacena la posicion en la tabla de simbolos.
//int yylval;  // para yyacc comentarlo

int cant_simbolos = 0; // mantener la ultima posicion de la tabla de simbolos
int tipoCte = 0; // almaceno temporalmente el tipo de constante que es, CTE_INT, CTE_REAL, CTE_HEX, CTE_STR
int cantidadDecimales = 0; // para validar la cantidad de decimales que tiene el float

using namespace std;

// String de cada token relacionado con un numero entero
char tokenNames[CANT_TOKENS+1][30] = {" ","<PR: BEGIN>","<PR: END>","<PR: VAR>","<PR: ENDVAR>","<PR: IF>","<PR: ELSE>","<PR: FI>","<PR: FOR>","<PR: ROF>","<PR: AND>", // palabras reservadas
                                      "<PR: OR>","<PR: NOT>","<PR: REAL>","<PR: INTEGER>","<PR: STRING>","<PR: WPRINT>","<PR: FTOC>","<PR: CTOF>","<PR: KTOC>","<PR: CTOK>", // palabras reservadas
                                      
                                      "<ID>","<CTE>","<OP_ASIG>","<OP_SUMA>","<OP_RESTA>","<OP_DIVISION>","<OP_MULTIPLIC>","<CTE_STR2>","<PARENABRE>",
                                      "<PARENCIERRA>","<CORCHABRE>","<CORCHCIERRA>","<LLAVEABRE>","<LLAVECIERRA>","<IGUAL>","<MENOR>","<MENORIGUAL>","<DISTINTO>","<MAYOR>",
                                      "<MAYORIGUAL>","<COMA>","<CTE_REAL>","<CTE_INT>","<CTE_STR>","<DOSPUNTOS>","<CONCAT>","<CTE_HEX>"};
                                      
                                    //  0      1       2      3        4      5      6      7      8      9     10
char palabraReservada[CANT_PR][10] = { " ", "BEGIN", "END", "VAR", "ENDVAR", "IF", "ELSE", "FI", "FOR", "ROF", "AND",
                                    //  11     12     13       14         15        16       17      18       19     20  
                                       "OR", "NOT", "REAL", "INTEGER", "STRING", "WPRINT", "FTOC", "CTOF", "KTOC", "CTOK" };      
 
// ========================================
// Prototipo de las funciones
// ========================================
//
void inicializar();
void cargarID (int idTS);
void cargarTipo (int tipo);
void nuevaDeclaracion ();
int maximoDeclaracion ();
int asignarTipoTablaSimbolos (int posTS);
int buscarPorId (int idTS);
int validarDeclaracion ();
char * buscarNombre (int idTS) ;
char * buscarValor (int idTS) ;
int buscarTipo (int idTS);
char * decodeTipo (int tipo);

void crearArchivoIntermedia(void);
void imprimirFuenteyPolacaPorPantalla(void);

int validarCambioBase (int numero, int base, int tipo);

// para el manejo de assembler
void generarASM(void);
void agregarHeaderASM(void);
void agregarEndASM(void);
void agregarVariablesTSASM(void);
void generarCodigoASM(void);    
void endASM(void);

// para yyacc
int yyparse(void);
int yyerror(char *);
int yylex(void);

////////////////////////////////////////////////
void generarPolaca (int, int, int );
char * getNombreOperador(int);
char * getNombreOperadorNegado ( int operador );
char * getCodigoOperador(int);
////////////////////////////////////////////////
char * getDescripcionError (int);
// devuelve en la lectura del archivo el caracter enviado, para volver a tomarlo
void devolverCaracter(char);
// retorna si la cadena enviada es una palabra reservada
int get_tkn_palabra_reservada(char strToken[]);
// guardar en la tabla de simbolos
int guardarTablaSimbolos (char strToken[],int tipoConstante, int tamanio, int tipo);
// devuelve el tipo de simbolo que esta leyendo, numero, letra, / , + , - ... para moverse sobre el automata
int get_evento      (char);
// funciones para el manejo del automata
////////////////////////////////////////////////
// error de carater leido
int Error           (char,char *,int *);
// inicia lectura de un id
int Inic_id         (char,char *,int *);
// continua lectura de un id
int Cont_id         (char,char *,int *);
// fin lectura de un id
int Fin_id          (char,char *,int *);
// inicia lectura de cte (real,int,hex)
int Inic_cte        (char,char *,int *);
// continua lectura de cte (real,int,hex)
int Cont_cte        (char,char *,int *);
// fin lectura de cte (real,int,hex)
int Fin_cte         (char,char *,int *);
// inicia lectura de cadena "....."
int Inic_cad        (char,char *,int *);
// continua lectura de cadena
int Cont_cad        (char,char *,int *);
// fin lectura de cadena
int Fin_cad         (char,char *,int *);
// inicia comentario -/
int Inic_comen      (char,char *,int *);
// continua comentario
int Cont_comen      (char,char *,int *);
// fin comentario /-
int Fin_comen       (char,char *,int *);
// ...
int Nada            (char,char *,int *);
// suma
int Op_suma         (char,char *,int *);
// lee una coma
int Coma            (char,char *,int *);
// inicia comparacion ==
int Inic_comp       (char,char *,int *);
// fin comparacion ==
int Fin_comp        (char,char *,int *);
// operador -
int Op_resta        (char,char *,int *);
// operador *
int Op_mult         (char,char *,int *);
// operador /
int Op_div          (char,char *,int *);
// operador :
int Dos_puntos      (char,char *,int *);
// operador (
int Par_abre        (char,char *,int *);
// operador )
int Par_cierra      (char,char *,int *);
// operador [
int Corch_abre      (char,char *,int *);
// operador ]
int Corch_cierra    (char,char *,int *);
// operador {
int Llave_abre      (char,char *,int *);
// operador }
int Llave_cierra    (char,char *,int *);
// inicio concatenacion ++
int Inic_conc       (char,char *,int *);
// fin concatenacion ++
int Fin_conc        (char,char *,int *);
////////////////////////////////////////////////

//MATRIZ DE CAMBIO DE ESTADOS
int nuevo_estado[][CANT_SIMBOLOS] = {
//          0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20   21
//          L   D   -   +   *   /   :   (   )   [   ]   {   }   "   =   >   <   .   ,  bl  ent  car-raros
/*Q0*/    { 1,  2,  4,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 25,  0,  0, 0},
/*Q1*/    { 1,  1, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q2*/    {28,  2, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF,  3, QF, QF, QF, QF},
/*Q3*/    {QF,  3, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q4*/    {QF, QF, QF, QF, QF,  5, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q5*/    { 5,  5,  5,  5,  5,  6,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 5},
/*Q6*/    { 5,  5,  0,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5,  5, 5},
/*Q7*/    {QF, QF, QF, 27, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q8*/    {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q9*/    {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q10*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q11*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q12*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q13*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q14*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q15*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q16*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q17*/   {17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, QF, 17, 17, 17, 17, 17, 17, 17, 17},
/*Q18*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, 19, QF, QF, QF, QF, QF, QF, QF},
/*Q19*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q20*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, 21, QF, QF, QF, QF, QF, QF, QF},
/*Q21*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q22*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, 23, 26, QF, QF, QF, QF, QF, QF},
/*Q23*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q24*/   {QF, 24, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q25*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q26*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q27*/   {QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF},
/*Q28*/   {28, 28, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF, QF}
};

// MATRIZ DE FUNCIONES             (estado del automata, caracter)
int (*mFunciones[][CANT_SIMBOLOS])(char,char *,int *) = {
//      0            1            2            3            4            5            6            7            8            9            10           11           12           13           14           15           16           17           18           19           20                      21
//      L            D            -            +            *            /            :            (            )            [            ]            {            }            "            =            >            <            .            ,            bl           ent                 car esp                      
/*Q0*/ {Inic_id,     Inic_cte,    Inic_comen,  Inic_conc,   Op_mult,     Op_div,      Dos_puntos,  Par_abre,    Par_cierra,  Corch_abre,  Corch_cierra,Llave_abre,  Llave_cierra,Inic_cad,    Inic_comp,   Inic_comp,   Inic_comp,   Inic_cte,    Coma,        Nada,        Nada,               Error},
/*Q1*/ {Cont_id,     Cont_id,     Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,      Fin_id,             Fin_id},
/*Q2*/ {Inic_cte,    Cont_cte,    Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Cont_cte,    Fin_cte,     Fin_cte,     Fin_cte,            Fin_cte},
/*Q3*/ {Fin_cte,     Cont_cte,    Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,            Fin_cte},
/*Q4*/ {Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,    Nada,        Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,    Op_resta,           Op_resta},
/*Q5*/ {Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,         Cont_comen},
/*Q6*/ {Cont_comen,  Cont_comen,  Fin_comen,   Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,  Cont_comen,   Cont_comen,  Cont_comen,        Cont_comen},
/*Q7*/ {Op_suma,     Op_suma,     Op_suma,     Fin_conc,    Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,     Op_suma,            Op_suma},
/*Q8*/ {Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q9*/ {Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q10*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q11*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q12*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q13*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q14*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q15*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q16*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q17*/{Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Fin_cad,     Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,    Cont_cad,           Cont_cad},
/*Q18*/{Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,           Fin_comp},
/*Q19*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q20*/{Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,           Fin_comp},
/*Q21*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q22*/{Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,    Fin_comp,           Fin_comp},
/*Q23*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},        
/*Q24*/{Fin_cte,     Cont_cte,    Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,            Fin_cte},
/*Q25*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},
/*Q26*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},
/*Q27*/{Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,        Nada,               Nada},
/*Q28*/{Cont_cte,    Cont_cte,    Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Fin_cte,     Cont_cte,    Fin_cte,     Fin_cte,     Fin_cte,            Fin_cte}
};
// =============================================================================
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////MAIN.C//////////////////////////////////////
    
int main(int argc, char *argv[]){    
    int token;
    printf("\n");
    string lPath = "test\\";
	string lPathCompleto;

  ////////////////////////////EJECUCION DE UN SOLO CASO//////////////////////////////////////
    if ((archivo=fopen("codigoFuente.txt","rt"))==NULL)    {
      printf("Error, no se encuentra el archivo\n");
      getch();
      exit(0);
    }
	
    inicializar();
    yyparse(); // para yyacc descomentar y comentar el while
    crearArchivoIntermedia();
    imprimirFuenteyPolacaPorPantalla();
    printf("\n");
    printf("==============================\n");
    printf("Contenido de Tabla de Simbolos\n");
    printf("==============================\n");

    printf("NOMBRE\t\t\tVALOR\t\t\tTIPO\n");
    printf("--------------------------------------------------------------------------------\n");
    for (int i=0;i<cant_simbolos;i++)
       printf("[%d] %s\t\t\t%s\t\t\t%s\n",i,tabla_simbolos[i].nombre,tabla_simbolos[i].valor,decodeTipo(tabla_simbolos[i].tipo));      

    fclose(archivo);
    printf("\n");
	

		
////////////////////////////EJECUCION DE UN MULTIPLES CASOS/////////////////////////////////////
/*		
	ifstream testCases ("test\\testCases.txt");
	if (testCases.is_open())
	{
		while (testCases.good())
		{
			getline(testCases,filename);
            lPathCompleto = lPath + filename;
			cout << "Ejecutando: " << filename << std::endl;
			inicializar();
			if ((archivo=fopen(lPathCompleto.c_str(),"rt"))==NULL)    {
               printf("Error, no se encuentra el archivo\n");
               getch();
               exit(0);
             }
			    try {
				   yyparse(); // para yyacc descomentar y comentar el while
				}
				catch (...) {
				 cout << "\n EXCEPTION";
				}
				
				crearArchivoIntermedia();
				//Imprime el contenido de la TS
    printf("\n");
    printf("==============================\n");
    printf("Contenido de Tabla de Simbolos\n");
    printf("==============================\n");

    printf("NOMBRE\t\t\tVALOR\t\t\tTIPO\n");
    printf("--------------------------------------------------------------------------------\n");
    for (int i=0;i<cant_simbolos;i++)
       printf("[%d] %s\t\t\t%s\t\t\t%s\n",i,tabla_simbolos[i].nombre,tabla_simbolos[i].valor,decodeTipo(tabla_simbolos[i].tipo));      

    
    printf("\n");

				
		}
		testCases.close();
	}
	else
	{
		cout << "Unable to open file" << endl << endl;
		getch();
        exit(0);
	}
*/
   fclose(archivo);
    
   printf("\n");
   system("PAUSE");
   return EXIT_SUCCESS;
}

/******************************************************************************/
// FUNCIONES CAMBIO DE ESTADO
// Reciben todos los parametros (aunque algunos no se usen) para no usar globales, 
// podria evitarse esto cambiando todo por variables globales
/******************************************************************************/
int Error     (char c,char strToken[],int *tam) {
   printf("%s\n",getDescripcionError(ERROR_CARACTER));
   return ERROR_CARACTER;
};

int Coma      (char c,char strToken[],int *tam) {devolverCaracter(c); return COMA;};

int Inic_id   (char c,char strToken[],int *tam){tipoCte = GENERICO; strToken[0] = c; *tam = 1; return 0;};

int Cont_id   (char c,char strToken[],int *tam) {
    if (*tam >= MAX_TAM_ID - 1) {
      printf("%s\n",getDescripcionError(ERROR_TAM_ID));
       return ERROR_TAM_ID; 
   }
    strToken[*tam] = c; 
    (*tam)++;
    return 0;
};

int Fin_id (char c,char strToken[],int *tam){
    int tknPalabraReservada = -1;
    strToken[*tam] = '\0';

    devolverCaracter(c);    

   // busco si es palabra reservada
   tknPalabraReservada = get_tkn_palabra_reservada(strToken);
   
   if (tknPalabraReservada >= 0){
      return tknPalabraReservada; // si es palabra reservada no se guarda en la tabla de simbolos
   }
   
   if (validarDeclaracion() == 1) { // error de la validacion
      printf("%s\n",getDescripcionError(ERROR_DECLARACION_DUPLICADA)); return ERROR_DECLARACION_DUPLICADA;
   }
    
   // guardar en la tabla de simbolos, si existe no lo genenera de nuevo
   yylval = guardarTablaSimbolos(strToken,tipoCte,*tam,ID);

   if (asignarTipoTablaSimbolos(yylval)<0) return -1; // error, no encuentra el id, el mensaje de error ya lo maneja la funcion

   if (finDeclaracion == 1) {
      if(buscarPorId(yylval) < 0) {
         printf("(!)ERROR: VARIABLE [%s] NO DECLARADA\n",buscarNombre(yylval));
         return -1;
      }
   }
    
   if (cant_simbolos >= CANT_TS) {printf("%s\n",getDescripcionError(ERROR_MAXIMO_TS)); return ERROR_MAXIMO_TS;}

   return ID;
};

int Inic_suma       (char c,char strToken[],int *tam){strToken[0] = c; return 0;};

int Fin_suma        (char c,char strToken[],int *tam){strToken[*tam] = c; devolverCaracter(c); return SUMA;};

int Inic_cte        (char c,char strToken[],int *tam) {

    strToken[*tam] = c; 
    (*tam)++;
    
    if (c=='.') tipoCte = CTE_REAL;
    else if (get_evento(c) == 0 )  tipoCte = CTE_HEX;
    else tipoCte = CTE_INT;  
           
    return 0;
};

int Cont_cte (char c,char strToken[],int *tam){
   
    if (*tam > MAX_TOKEN) {
       printf("%s\n",getDescripcionError(ERROR_MAXIMO_TOKEN));
       return ERROR_MAXIMO_TOKEN;
    }
    
   // SI EMPEZO LEYENDO UN NUMERO Y APARECE UNA LETRA PUEDE ES UN NUMERO HEXADECIMAL
    if (get_evento(c) == 0 ) tipoCte = CTE_HEX;
       
    if (tipoCte!= CTE_HEX && c=='.') tipoCte = CTE_REAL;

    strToken[*tam] = c; 
    (*tam)++;

    return 0;
}

int Fin_cte (char c,char strToken[],int *tam){

    devolverCaracter(c);
   
    // valido si el rango es correcto
    if (tipoCte == CTE_INT && (atof(strToken) < MIN_INT || atof(strToken) > MAX_INT)) {
      printf("%s\n",getDescripcionError(ERROR_RANGO_INT));
      return ERROR_RANGO_INT;
   }
    // valido el rango del float
    if (tipoCte == CTE_REAL && (atof(strToken) < MIN_FLOAT || atof(strToken) > MAX_FLOAT)){
      printf("%s\n",getDescripcionError(ERROR_RANGO_FLOAT));
      return ERROR_RANGO_FLOAT;
   }
    if (tipoCte == CTE_HEX && strlen(strToken) > MAX_HEX){
      printf("%s\n",getDescripcionError(ERROR_HEX));
      return ERROR_HEX;
   }
    
    // guardar en la tabla de simbolos, si existe no lo genenera de nuevo
    yylval = guardarTablaSimbolos(strToken,tipoCte,*tam,CTE);
    
    if (cant_simbolos >= CANT_TS) {printf("%s\n",getDescripcionError(ERROR_MAXIMO_TS)); return ERROR_MAXIMO_TS;}

    return tipoCte;    
};


int Op_asig         (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return OP_ASIG;};
int Nada            (char c,char strToken[],int *tam){return 0;};

int Inic_comp       (char c,char strToken[],int *tam){strToken[0] = c; *tam = 1; return 0;};
int Fin_comp        (char c,char strToken[],int *tam){
   strToken[*tam] = c; 
   (*tam)++;
   if (strToken[0] == '<') {
      devolverCaracter(c);   
      switch (strToken[1]) {
   
         case '>': return DISTINTO;
         case '=': return MENORIGUAL;
         default : return MENOR;
      }
   }
   else if (strToken[0] == '>') {
      devolverCaracter(c);   
      switch (strToken[1]) {
         case '=': return MAYORIGUAL;
         default : return MAYOR;
      }
   }
   else if (strToken[0] == '=') {
      devolverCaracter(c);    
      switch (strToken[1]) {
         case '=': return IGUAL;
         default: return OP_ASIG;
      }
   }
};

int Op_resta        (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return RESTA;};
int Op_suma         (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return SUMA;};
int Op_mult         (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return MULTIPLIC;};
int Op_div          (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return DIVISION;};
int Dos_puntos      (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return DOSPUNTOS;};

int Par_abre        (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return PARENABRE;};
int Par_cierra      (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return PARENCIERRA;};
int Corch_abre      (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return CORCHABRE;};
int Corch_cierra    (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return CORCHCIERRA;};
int Llave_abre      (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return LLAVEABRE;};
int Llave_cierra    (char c,char strToken[],int *tam){strToken[0] = c; devolverCaracter(c); return LLAVECIERRA;};

int Inic_cad        (char c,char strToken[],int *tam){
   tipoCte = CTE_STR; 
   /*strToken[*tam] = c; 
   (*tam)++; 
   */
   return 0;
};

int Cont_cad        (char c,char strToken[],int *tam){
    // valido que no supere el maximo de string
    if (*tam > MAX_TAM_ID - 1) {
      printf("%s\n",getDescripcionError(ERROR_STRING_MAX));
      return ERROR_STRING_MAX;
   }

    strToken[*tam] = c; 
    (*tam)++;

    // si llego a fin de archivo , y estoy aca, es porque no cerro las comillas    
    if (feof(archivo)) {
      printf("%s\n",getDescripcionError(ERROR_STRING_CIERRE));
      return ERROR_STRING_CIERRE;
   }
   
   return 0;
};

int Fin_cad         (char c,char strToken[],int *tam) {  
  /*  strToken[*tam] = c; 
    (*tam)++;
    */
    // guardar en la tabla de simbolos, si existe no lo genenera de nuevo
    yylval = guardarTablaSimbolos(strToken,tipoCte,*tam,CTE);
    
    if (cant_simbolos >= CANT_TS) {printf("%s\n",getDescripcionError(ERROR_MAXIMO_TS)); return ERROR_MAXIMO_TS;}

    return CTE_STR;    
};

int Inic_comen      (char,char *,int *){return 0;};

int Leer_comen      (char,char *,int *){
    // si llego a fin de archivo , y estoy leyendo comentarios es porque no lo cerro todavia
    if (feof(archivo)) {
      printf("%s\n",getDescripcionError(ERROR_COMEN_CIERRE));
      return ERROR_COMEN_CIERRE;
   } 
       
    return 0;   
}

int Cont_comen      (char,char *,int *){
    // si llego a fin de archivo , y estoy aca, es porque no cerro el comentario
    if (feof(archivo)) {
      printf("%s\n",getDescripcionError(ERROR_COMEN_CIERRE));
      return ERROR_COMEN_CIERRE;
   } 
    
    return 0;
};

int Fin_comen       (char,char *,int *){return GENERICO;};

int Inic_conc       (char c,char strToken[],int *tam){strToken[0] = c; return 0;};

int Fin_conc        (char c,char strToken[],int *tam){ 
    devolverCaracter(c);   
    strToken[*tam] = c; 
                                       (*tam)++;
                                       return CONCAT;};

int yyerror(char* c)
{
    printf("%s\n",c);
    getch();
    exit(1);
    return -1;
}


void devolverCaracter(char c)
{
   if ((c!=' ') && (c!='\n'))
     ungetc(c,archivo);
}

// esta funcion devuelve la columna a mirar en la matriz de estados segun el caracter
int get_evento(char c)
{
   if(isalpha(c))
     return 0;
   else
   {
      if(isdigit(c))
         return 1;
      else
      {
         switch(c)
         {
            case '-' : return  2;
            case '+' : return  3;
            case '*' : return  4;
            case '/' : return  5;
            case ':' : return  6;
            case '(' : return  7;
            case ')' : return  8;
            case '[' : return  9;
            case ']' : return  10;
            case '{' : return  11;
            case '}' : return  12;
            case '"' : return  13;
            case '=' : return  14;
            case '>' : return  15;
            case '<' : return  16;                                        
            case '.' : return  17;
            case ',' : return  18; 
            case ' ' : return  19;
            case '\t': return  19;
                case '\n': return  20;
                case EOF : return  20;
            default  : return  21; // si es otro caracter, ver otros estados...
         }
      }
   }    
}

int yylex(void)
{
    int estado = 0;
    int estado_final = QF;
    int columna = 0;  //columna a buscar en matrices
    int token = 0, newToken = 0;
    char strToken[MAX_TIPO] = {'\0'}; //va almacenando la cadena del indentificador
    int tamToken = 0;  //indice que indica el tamanio del identificador
    char c;
    yylval = -1;

    while ((estado != estado_final) && !feof(archivo))
    {
            c = getc(archivo);  // Obtiene proximo caracter

            columna = get_evento(c); // obtiene columna para buscar en las matrices
         
            newToken = (*mFunciones[estado][columna])(c,strToken,&tamToken); //ejecuta funcion
         
            switch (c) {
             case '\n':
             case EOF: coltxt=0;lineatxt++;break;
             case '\t': coltxt+=4;break;
             default: coltxt++;
           }
                 
            if (newToken != 0)  
               token = newToken; // solo asigno en el token a retornar si el newToken es distinto de 0 para no pisar un resultado anterior
   
            if (token < 0)  // si el token es < 0 hubo error, salgo
                return token;
          
            if (tamToken > MAX_TOKEN) {
             printf("%s\n",getDescripcionError(ERROR_MAXIMO_TOKEN));
                return ERROR_MAXIMO_TOKEN;
          }
            estado = nuevo_estado[estado][columna]; //busco y actualizo nuevo estado    
    }
      
    return token;  
} 

// devuelve el numero correspondiente al Token si encuentra palabra reservada o -1 si NO es palabra reservada
// busca el numero correspondiente en el vector
int get_tkn_palabra_reservada(char strToken[]){
   int i;
   for (i=1;i<CANT_PR;i++)
      if (strcmpi(strToken,palabraReservada[i])==0)
         switch (i) {
                case 1:  return BEGIN;
                case 2:  return END;
                case 3:  return VAR;
                case 4:  return ENDVAR;
                case 5:  return IF;
                case 6:  return ELSE;
                case 7:  return FI;
                case 8:  return FOR;
                case 9:  return ROF;
                case 10: return AND;
                case 11: return OR;
                case 12: return NOT; 
                case 13: return REAL; 
                case 14: return INTEGER; 
                case 15: return STRING; 
                case 16: return WPRINT; 
                case 17: return FTOC;                                                                                 
                case 18: return CTOF; 
                case 19: return KTOC;                         
                case 20: return CTOK;                    
         };
   return -1;
}

int guardarTablaSimbolos (char strToken[], int tipoConstante, int tamanio, int tipo) {
    
    int posicionTS = -1, j;
    char constante[50];
   
    if (tipo==CTE && tipoConstante!=CTE_STR) {
       strcpy(constante,"_");
       strcat(constante,strToken);
       strcat(constante,"\0");
       if (tipoConstante == CTE_REAL)     //reemplazo el punto porque me falla en asm
          for (int i=0; i < tamanio; i++)
             if (constante[i] == '.')
                constante[i] = 'p';            
    } else if (tipo==CTE && tipoConstante==CTE_STR) {
	    // lo busco por valor
		strcpy(constante,"\"");
		strcat(constante,strToken);
		strcat(constante,"\"");
		strcat(constante,"\0");		
	} else {
       strcpy(constante,strToken);  
    }
    
    for(j=0;j<cant_simbolos;j++) {
      if (strcmp(constante, tabla_simbolos[j].nombre)==0) posicionTS = j;
	  if (tipo==CTE && tipoConstante==CTE_STR && strcmp(constante, tabla_simbolos[j].valor)==0) posicionTS = j;
    }

    // significa que lo encontro, retorna la posicion
    if (posicionTS != -1)
       return posicionTS;
    else {
         // sino lo guardo en la tabla de simbolos    
         if (tipo == CTE) {
            
			    if (tipoConstante == CTE_STR) {
				    sprintf(tabla_simbolos[cant_simbolos].nombre,"_cteStr%d",cantidadCTE);
				    cantidadCTE++;
			    } else {
            /*
				    tabla_simbolos[cant_simbolos].nombre[0] = '_';
				    tabla_simbolos[cant_simbolos].nombre[1] = '\0';
            */
			    	strcat(tabla_simbolos[cant_simbolos].nombre,constante);            
			    }      
				
			    if (tipoConstante == CTE_STR) {
			    	strcpy(constante,"\"");
			    	strcat(constante,strToken);
				    strcat(constante,"\"");
				    strcat(constante,"\0");
				    strcpy(tabla_simbolos[cant_simbolos].valor,constante);
			    } else if (tipoConstante == CTE_INT) {
				    strcat(strToken,".0"); // agrego .0 para los INTEGER
					strcpy(tabla_simbolos[cant_simbolos].valor,strToken);
				} else {
				    strcpy(tabla_simbolos[cant_simbolos].valor,strToken);
		    	}
         } else {
               strcpy(tabla_simbolos[cant_simbolos].nombre,strToken);
               if (tipoConstante == CTE_REAL)     //reemplazo el punto porque me falla en asm
                  for (int i=0; i < tamanio; i++)
                     if (tabla_simbolos[cant_simbolos].nombre[i] == '.')
                        tabla_simbolos[cant_simbolos].nombre[i] = 'p'; 
         }
    tabla_simbolos[cant_simbolos].tipo      = tipoConstante;
    tabla_simbolos[cant_simbolos].longitud  = tamanio;    
    // aumento el index del vector
    cant_simbolos++;
    // retorno en la posicion en que fue guardado         
    return cant_simbolos-1;
    }
}

char * getDescripcionError ( int error ) {
    static char errores[100];
    static char mensaje[512];
   
   switch (error) 
   {
      case ERROR_RANGO_INT: strcpy(errores,"NUMERO ENTERO FUERA DE RANGO");break;
      case ERROR_RANGO_FLOAT: strcpy(errores,"NUMERO REAL FUERA DE RANGO");break;  
      case ERROR_STRING_MAX: strcpy(errores,"MAXIMO DE STRING SUPERADO");break;       
      case ERROR_STRING_CIERRE: strcpy(errores,"FALTA CIERRE DE STRING");break;            
      case ERROR_COMEN_CIERRE: strcpy(errores,"FALTA CIERRE DE COMENTARIO");break;
      case ERROR_CARACTER: strcpy(errores,"CARACTER INVALIDO");break;
      case ERROR_HEX: strcpy(errores,"NUMERO HEXADECIMAL");break;
      case ERROR_TAM_ID: strcpy(errores,"TAMANIO MAXIMO DE ID");break;
      case ERROR_NO_EXISTE_ID: strcpy(errores,"NO EXISTE ID");break;
      case ERROR_DECLARACION_DUPLICADA: strcpy(errores,"DECLARACION DUPLICADA");break;
      case ERROR_MAXIMO_TOKEN: strcpy(errores,"MAXIMO DE TOKEN SUPERADO");break;
     case ERROR_MAXIMO_TS: strcpy(errores,"MAXIMO DE ENTRADA PARA LA TS");break;
      default : strcpy(errores,"GENERICO");break;
   }
   sprintf(mensaje, "(!)ERROR[%d][%d]: %s", lineatxt, coltxt, errores);
   
   return mensaje;
}

char *  buscarNombre (int idTS) {
   return tabla_simbolos[idTS].nombre;
}

int  buscarTipo (int idTS) {
   return tabla_simbolos[idTS].tipo;
}

char *  buscarValor (int idTS) {
   return tabla_simbolos[idTS].valor;
}

void inicializar () {
   for (int i=0;i<MAX_IDS;i++) {
      vec[i].id = -1;
      vec[i].tipo = -1;
      vec[i].valido = INICIAL;
   }   
   // limpio variables globales para poder compilar varios fuentes
   
   // limpio tabla de simbolos   
   for (int i=0;i<CANT_TS;i++) {
      tabla_simbolos[i].nombre[0] = '\0';
	  tabla_simbolos[i].tipo = -1;
	  tabla_simbolos[i].valor[0] = '\0';
	  tabla_simbolos[i].longitud = -1;
   }
   
	//vAnidamiento.clear()
	while (!vAnidamiento.empty())
	   vAnidamiento.pop();
	   
	//vPIla.clear()
    while (!vPila.empty())
	   vPila.pop();	 
	   
    vPolaca.clear();	   
	id_decla = 0;
	tipo_decla = 0;
	finDeclaracion = 0;
	lineatxt = 1;
    coltxt= 1;
	cant_simbolos = 0;
	tipoCte = 0;
	cantidadDecimales=0;   
}

void cargarID (int idTS) {
     vec[id_decla].id = idTS;                  
     id_decla++;
}

void cargarTipo (int tipo) {
     vec[tipo_decla].tipo = tipo;                  
     tipo_decla++;
}

int buscarPorId (int idTS) {

   for(int i=0;i<maximoDeclaracion();i++) {
      if (vec[i].id == idTS) {
         switch(vec[i].valido) {
          case VALIDO: return i;
         case INICIAL: return CONTINUAR;
         case INVALIDO: return ERROR_BUSCAR;       
       }
      }
   }

   return CONTINUAR;
}

/*
Valida todos los ids, y tipos guardados hasta el momento en el vector (vec),
validarDeclaracion devuelve error, cuando encuentra al menos uno INVALIDO, si no encuentra ningun par (id,tipo) completo, devuelve ok.
Primero recorro todo el vector, hasta donde se cargo (maximoDeclaracion), y por cada par (id,tipo) que tenga algo (!=-1), y que se encuentre en
INICIAL O VALIDO (verifica si esta duplicado), verifico, que no haya otro con igual ID, y que tenga algo tipo ingresado, sino pone ambos registros como invalidos.
*/

int validarDeclaracion () {
   int flag = 0;
   for(int i=0;i<maximoDeclaracion();i++) {
      if(vec[i].tipo != -1 && vec[i].id != -1 && vec[i].valido != INVALIDO ) { // puede ser que sea valido, hay que ver que no exista otro tambien completo
         vec[i].valido = VALIDO;
         for(int j=i+1;j<maximoDeclaracion();j++) {
            if(vec[j].tipo != -1 /*algun tipo*/ && vec[j].id == vec[i].id) { // hay dos variables declaras es error para las dos
               vec[j].valido = INVALIDO;
               vec[i].valido = INVALIDO;
               flag = 1;
            }
         }
       }
   }
   return flag;
}


void nuevaDeclaracion () {
   int resultado;
     if (id_decla>tipo_decla)
        tipo_decla = id_decla;
     else
         id_decla = tipo_decla;

   resultado = validarDeclaracion();
   
   for (int i=0;i<maximoDeclaracion();i++) {
      if (vec[i].valido == VALIDO) {
         tabla_simbolos[vec[i].id].tipo = vec[i].tipo;
      }
   }
}

int maximoDeclaracion () {
   if (id_decla > tipo_decla)
     return id_decla;
   else
     return tipo_decla;
}

int asignarTipoTablaSimbolos(int posTS) {
   int posDeclaracion = buscarPorId(posTS); // busco por indice de tabla de simbolos, lo busco en el vector se ids,tipos

   switch(posDeclaracion) {
      case ERROR_BUSCAR: printf("%s\n",getDescripcionError(ERROR_DECLARACION_DUPLICADA)); return ERROR_DECLARACION_DUPLICADA; // si esta duplicado pincha
     case CONTINUAR: return OK;   // si no enc
   }
   
   tabla_simbolos[cant_simbolos].tipo = vec[posDeclaracion].tipo;
   
   return OK;
}

int validarCambioBase (int numero, int base, int tipo) {
   int tipoBase;
   int maxCadena;
   char numeroCadena[100];
   int valor;
   //
   int mul=1;
   char numeroChar[10];
   int numeroDecimal=0;
   //
   
   tipoBase = atoi(buscarValor(base));
   
   if(tipo==CTE) {
      strcpy(numeroCadena,buscarValor(numero));
   } else {
      strcpy(numeroCadena,buscarNombre(numero));  
   }

   if (tipoBase != 2 && tipoBase != 16) {
      printf("ERROR: [%d] BASE INCORRECTA\n",tipoBase);
      getch();
      return -1;
   }
   
   // numero lo tendre que tratar como char...
   if (tipoBase == 2) {
      // solo puede tener 0 y 1
      for (int i=0;i<strlen(numeroCadena);i++) {
         if (numeroCadena[i] != '0' && numeroCadena[i] != '1' && numeroCadena[i] != '.') {
            printf("ERROR: [%s] NO ES UN NUMERO BINARIO\n",numeroCadena);
            getch();
            return -1;
         }
      }
	  
	  // lo paso a decimal para poder operar
	  for (int i=strlen(numeroCadena)-3;i>=0;i--) {
         sprintf(numeroChar,"%c",numeroCadena[i]);
         numeroDecimal+=(atoi(numeroChar)*mul);
         mul*=2;        
      }
	  sprintf(numeroCadena,"%d",numeroDecimal);
	  valor = guardarTablaSimbolos(numeroCadena,CTE_INT,strlen(numeroCadena),CTE);
	  
	  generarPolaca(CTE,valor,0);
	  
	  
   } else {
     // solo puede tener 0 1 2 3 4 5 6 7 8 9 A B C D E F
      for (int i=0;i<strlen(numeroCadena);i++) {
         if ( numeroCadena[i] != '0' && numeroCadena[i] != '1' && numeroCadena[i] != '2' && numeroCadena[i] != '3' && numeroCadena[i] != '4' &&
              numeroCadena[i] != '5' && numeroCadena[i] != '6' && numeroCadena[i] != '7' && numeroCadena[i] != '8' && numeroCadena[i] != '9' &&
              numeroCadena[i] != 'A' && numeroCadena[i] != 'B' && numeroCadena[i] != 'C' && numeroCadena[i] != 'D' && numeroCadena[i] != 'E' &&
              numeroCadena[i] != 'F' &&
              numeroCadena[i] != 'a' && numeroCadena[i] != 'b' && numeroCadena[i] != 'c' && numeroCadena[i] != 'd' && numeroCadena[i] != 'e' &&
              numeroCadena[i] != 'f'
             ) {
            printf("ERROR: [%s] NO ES UN NUMERO HEXADECIMAL\n",numeroCadena);
            getch();
            return -1;
         }
      }  
      if (strlen(numeroCadena) > MAX_HEX){
         printf("%s\n",getDescripcionError(ERROR_HEX));
         getch();
         return ERROR_HEX;
      }
	  
      numeroDecimal = (int)strtol(numeroCadena, NULL, 16);
	   
	  sprintf(numeroCadena,"%d",numeroDecimal);
      valor = guardarTablaSimbolos(numeroCadena,CTE_INT,strlen(numeroCadena),CTE);
	  
	  generarPolaca(CTE,valor,0);
	  
   }
  return 1;
}

char * decodeTipo ( int tipo ) {
   switch(tipo) {
      case CTE_HEX: return "CTE_HEX";
      case CTE_INT: return "CTE_INT";
      case CTE_REAL: return "CTE_REAL";
      case CTE_STR: return "CTE_STR";
	  case INTEGER: return "INTEGER";
	  case REAL: return "REAL";
	  case STRING: return "STRING";
      default : return "GEN";
   }
}   

void agregarHeaderASM() {
// metiraba error y como no tengo idea pegue el otro codigo del tp
   fprintf(archivoASM,".MODEL LARGE\n");  
   fprintf(archivoASM,".386\n");
   fprintf(archivoASM,".STACK 200h\n");
   fprintf(archivoASM,".DATA\n");
   fprintf(archivoASM," SALIR db \"OPRIMA UNA TECLA PARA SALIR\",0Dh, 0Ah,'$'\n");             
}

void agregarEndASM() { 
// metiraba error y como no tengo idea pegue el otro codigo del tp
  fprintf(archivoASM,";RUTINA END\n");
  fprintf(archivoASM,"\tmov DX,OFFSET SALIR\n\tmov ah,09   \n\tint 21h\n");
  fprintf(archivoASM,"\tmov ah,1\n\tint 21h\n\tmov AX,4C00h\n\tint 21h\n");
  fprintf(archivoASM,"\tend START;\n");  
  fprintf(archivoASM,"\tend;\n");  
  fprintf(archivoASM,";FIN RUTINA END\n");
}

void generarASM() {
   int op1, op2, op3, op4, comparacion, etiqueta, comp2, comp1;
   char aux[4];
   int cant_aux = 1;
   int aux_id_etiqueta;
   int mostrar=0;
   
   if ((archivoASM=fopen("fuente.asm","wt"))==NULL) {
      printf("Error, no se encuentra el archivo\n");
      getch();
      exit(0);
   }

   printf("INICIO ASSEMBLER\n");
   printf("GENERO LA CABECERA\n");
   
   /* generamos el principio del assembler, que siempre es igual */
   fprintf(archivoASM, ".MODEL\tLARGE\n");
   fprintf(archivoASM, ".386 \n");
   fprintf(archivoASM, ".STACK 200h \n");
   fprintf(archivoASM, ".CODE \n");
   fprintf(archivoASM, "\n\t ;INICIALIZACION\n");
   fprintf(archivoASM, "\t mov AX, @DATA \n");
   fprintf(archivoASM, "\t mov DS, AX \n");
   fprintf(archivoASM, "\n \t ;INICIO PROGRAMA \n");

  
   for (int i=0;i<=vPolaca.size();i++){   
	  // verifico si en esta posicion tiene que ir alguna etiqueta...
	  for (int j=0;j<id_etiqueta;j++) {
         if (etiquetas[j].posicion==i) {
			fprintf(archivoASM, "\t %s: \n", etiquetas[j].nombre);		

		 }
 	  }

      if (vPolaca[i].tipo==POSICION) { // para hacer saltos
	  
	     etiqueta = vPolaca[i].valor;
	     etiquetas[id_etiqueta].posicion = etiqueta;
		 sprintf(etiquetas[id_etiqueta].nombre,"etiqueta_%d",etiqueta);
		 fprintf(archivoASM, "\t JMP etiqueta_%d \n", etiqueta);	
		 id_etiqueta++;	  
	  } else if (vPolaca[i].tipo==ETIQUETA) {
         fprintf(archivoASM, "\t etiqueta_%d: \n", vPolaca[i].valor); // etiqueta para el for
	  
	  } else if (vPolaca[i].tipo==OPERADOR) { // es un operador, wprint + = ...
	     if (vPolaca[i].valor==WPRINT) {
			
			op1 = vPila.top();
			vPila.pop();
			if (buscarTipo(op1) == CTE_STR || buscarTipo(op1) == STRING ) {
				fprintf(archivoASM,"\t ;IMPRESION DE STRING\n" );
				// tomo el valor lo ultimo de la pila, imprime solo strings...
				fprintf(archivoASM, "\t mov DX, OFFSET %s \n", buscarNombre(op1));
				fprintf(archivoASM, "\t mov ah, 9 \n");
				fprintf(archivoASM, "\t int 21h \n");
         				
			} else if (buscarTipo(op1) == CTE_INT || buscarTipo(op1) == INTEGER ) {
				fprintf(archivoASM,"\t ;IMPRESION DE INTEGER\n" );
				fprintf(archivoASM,"\t mov eax, %s \n",buscarNombre(op1));
				fprintf(archivoASM,"\t mov ecx, 10 \n");
				fprintf(archivoASM,"\t xor bx, bx \n");
				fprintf(archivoASM,"\t division_%d: \n",mostrar);
				fprintf(archivoASM,"\t xor edx, edx \n");
				fprintf(archivoASM,"\t div ecx \n");
				fprintf(archivoASM,"\t push dx \n");
				fprintf(archivoASM,"\t inc bx \n");
				fprintf(archivoASM,"\t test eax, eax \n");
				fprintf(archivoASM,"\t jnz division_%d \n",mostrar);
				fprintf(archivoASM,"\t mov cx, bx \n");
				fprintf(archivoASM,"\t lea si, __cadenaAux \n");
				fprintf(archivoASM,"\t obtenerDigito_%d: \n",mostrar);
				fprintf(archivoASM,"\t pop ax \n");
				fprintf(archivoASM,"\t add al, '0' \n");
				fprintf(archivoASM,"\t mov [si], al \n");
				fprintf(archivoASM,"\t inc si \n");
				fprintf(archivoASM,"\t loop obtenerDigito_%d \n",mostrar);
				fprintf(archivoASM,"\t mov al, '$' \n");
				fprintf(archivoASM,"\t mov [si], al \n");
				fprintf(archivoASM,"\t lea dx, __cadenaAux \n");
				fprintf(archivoASM,"\t mov ah, 9 \n");
				fprintf(archivoASM,"\t int 21h \n");
				fprintf(archivoASM, "\t mov DX, OFFSET __cadenaVacia \n");
				fprintf(archivoASM, "\t mov ah, 9 \n");
				fprintf(archivoASM, "\t int 21h \n");				
				
				mostrar++;
			}
			
         } else if ((vPolaca[i].valor == IGUAL) || (vPolaca[i].valor == DISTINTO) || (vPolaca[i].valor == MENOR) || (vPolaca[i].valor == MAYOR) || (vPolaca[i].valor == MENORIGUAL) || (vPolaca[i].valor == MAYORIGUAL )) {
            vPila.push(vPolaca[i].valor);
			
		 } else if (vPolaca[i].valor==OP_ASIG) {
		    do {
               // cuando llega una asignacion leo hasta que se vacia la pila
   		       op1 = vPila.top(); vPila.pop();
    	       op2 = vPila.top(); vPila.pop();
        
			   if ((buscarTipo(op1) == STRING || buscarTipo(op1) == CTE_STR ) && (buscarTipo(op2) == CTE_STR || buscarTipo(op2) == STRING)) {
		  	      // si ambos tipos son strings...
	  		      fprintf(archivoASM,"\t ;ASIGNACION STRING\n" );
  			      fprintf(archivoASM,"\t mov es, ax \n" );
  			      fprintf(archivoASM,"\t mov cl, MAXTEXTSIZE \n");
  			      fprintf(archivoASM,"\t mov si, OFFSET %s; Origen \n", buscarNombre(op1));
  			      fprintf(archivoASM,"\t mov di, OFFSET %s; Destino \n",buscarNombre(op2));
  			      fprintf(archivoASM,"\t rep movsb \n");
  			
			   } else if (buscarTipo(op1) != CTE_STR && buscarTipo(op1) != STRING && buscarTipo(op2) != CTE_STR || buscarTipo(op2) != STRING) { 
                  fprintf(archivoASM,"\t ;ASIGNACION REAL\n" );
                  fprintf(archivoASM, "\t FLD %s;\n", buscarNombre(op1));
                  fprintf(archivoASM, "\t FSTP %s;\n", buscarNombre(op2));			   
               }
			   
			   vPila.push(op2);
			   
			} while (vPila.size() > 1);
			
			vPila.pop();
			
          } else if (vPolaca[i].valor==SUMA || vPolaca[i].valor==RESTA || vPolaca[i].valor==DIVISION || vPolaca[i].valor==MULTIPLIC ){
		     // FALTA VALIDAR QUE SE HAGAN OPERACIONES CON TIPOS CONOCIDOS!!!!
             fprintf(archivoASM,"\t ;SUMA o DIV o MUL o SUB ETC\n" );
             op1 = vPila.top(); vPila.pop();
    	     op2 = vPila.top(); vPila.pop();
		     /*insertamos variables auxiliares en TS si no estan */          					
		     fprintf(archivoASM, "\t FLD %s;\n", buscarNombre(op1));
		     fprintf(archivoASM, "\t FLD %s;\n", buscarNombre(op2));
             sprintf(aux, "_aux%d", cant_aux++);
             yylval = guardarTablaSimbolos(aux,REAL,0,REAL);
		     /*caso especial que no son comutativos, debo intercambiar operadores para que queden bien*/
		     if((vPolaca[i].valor==RESTA) || (vPolaca[i].valor==DIVISION)) {
                fprintf(archivoASM, "\t FXCH;\n");
		     }
		     fprintf(archivoASM, "\t %s;\n", getCodigoOperador(vPolaca[i].valor));
		     fprintf(archivoASM, "\t FSTP %s;\n", aux);
             //apilo auxiliar
             vPila.push(yylval);
			 
		 } else if (vPolaca[i].valor==CMP) {
		      
			  /* en las dos posiciones siguientes, 
			     1era- tengo la etiqueta a donde tiene que saltar para ir a la parte falsa
                 2da- y en la siguiente tengo el tipo de comparacion, si es simple, < > == ..., si es compuesta && , ||
			  */
			  i++;
			  etiqueta = vPolaca[i].valor; // 1era
			  i++;
			  comparacion = vPolaca[i].valor; // 2da
			  
			  if (comparacion==IGUAL || comparacion==MENOR || comparacion==MENORIGUAL || comparacion==DISTINTO || comparacion==MAYOR || comparacion==MAYORIGUAL) {
			      fprintf(archivoASM,"\t ;COMPARACION SIMPLE\n" ); 
			  	  // tengo que tomar los dos valores de la pila, porque es una comparacion simple, y en la pila tengo los dos valores a comparar
				  // ej: a, b
                  op1 = vPila.top(); vPila.pop();
                  op2 = vPila.top(); vPila.pop();
				  //
				  fprintf(archivoASM, "\t FLD %s \n", buscarNombre(op1));
				  fprintf(archivoASM, "\t FLD %s \n", buscarNombre(op2));
				  fprintf(archivoASM, "\t FCOMP \n");
				  fprintf(archivoASM, "\t FFREE ST(0) \n");
				  fprintf(archivoASM, "\t FSTSW AX \n");
				  fprintf(archivoASM, "\t SAHF \n");
				  fprintf(archivoASM, "\t %s etiqueta_%d \n", getNombreOperador(comparacion), etiqueta);		
				  
				  etiquetas[id_etiqueta].posicion = etiqueta;
				  sprintf(etiquetas[id_etiqueta].nombre,"etiqueta_%d",etiqueta);
				  id_etiqueta++;	  
			  } else if (comparacion==AND || comparacion==OR) {
			     fprintf(archivoASM,"\t ;COMPARACION COMPUESTA\n" ); 
				 // ej:  en la pila estaria:
				 // JNE, d, c, JNA, b, a
				 comp2 = vPila.top(); vPila.pop();
				 op4 = vPila.top(); vPila.pop();
				 op3 = vPila.top(); vPila.pop();
				 comp1 = vPila.top(); vPila.pop();
				 op2 = vPila.top(); vPila.pop();
				 op1 = vPila.top(); vPila.pop();
				 
				 if (comparacion == AND) {
				    // si es and para que vaya a la parte false tiene que no cumplir alguna
				    fprintf(archivoASM, "\t FLD %s \n", buscarNombre(op2));
				    fprintf(archivoASM, "\t FLD %s \n", buscarNombre(op1));
				    fprintf(archivoASM, "\t FCOMP \n");
				    fprintf(archivoASM, "\t FFREE ST(0) \n");
				    fprintf(archivoASM, "\t FSTSW AX \n");
				    fprintf(archivoASM, "\t SAHF \n");
				    fprintf(archivoASM, "\t %s etiqueta_%d \n", getNombreOperador(comp1), etiqueta); // sino cumple parte falsa
                    //
				    fprintf(archivoASM, "\t FLD %s \n", buscarNombre(op4));
				    fprintf(archivoASM, "\t FLD %s \n", buscarNombre(op3));
				    fprintf(archivoASM, "\t FCOMP \n");
				    fprintf(archivoASM, "\t FFREE ST(0) \n");
				    fprintf(archivoASM, "\t FSTSW AX \n");
				    fprintf(archivoASM, "\t SAHF \n");
				    fprintf(archivoASM, "\t %s etiqueta_%d \n", getNombreOperador(comp2), etiqueta); // sino cumple parte falsa
                    //
				    etiquetas[id_etiqueta].posicion = etiqueta;
				    sprintf(etiquetas[id_etiqueta].nombre,"etiqueta_%d",etiqueta);
				    id_etiqueta++;	  					
					//				 
				 } else if (comparacion == OR ) {
				    // si es or para que vaya a la parte false tiene que no cumplir las dos
				    fprintf(archivoASM, "\t FLD %s \n", buscarNombre(op2));
				    fprintf(archivoASM, "\t FLD %s \n", buscarNombre(op1));
				    fprintf(archivoASM, "\t FCOMP \n");
				    fprintf(archivoASM, "\t FFREE ST(0) \n");
				    fprintf(archivoASM, "\t FSTSW AX \n");
				    fprintf(archivoASM, "\t SAHF \n");
				    fprintf(archivoASM, "\t %s etiqueta_%d \n", getNombreOperadorNegado(comp1), etiqueta + 1); // si cumple parte verdadera
                    //
				    fprintf(archivoASM, "\t FLD %s \n", buscarNombre(op4));
				    fprintf(archivoASM, "\t FLD %s \n", buscarNombre(op3));
				    fprintf(archivoASM, "\t FCOMP \n");
				    fprintf(archivoASM, "\t FFREE ST(0) \n");
				    fprintf(archivoASM, "\t FSTSW AX \n");
				    fprintf(archivoASM, "\t SAHF \n");
				    fprintf(archivoASM, "\t %s etiqueta_%d \n", getNombreOperador(comp2), etiqueta); // sino la cumple parte falsa
					//
					fprintf(archivoASM, "\t etiqueta_%d: \n", etiqueta + 1); // parte verdadera
                    //				
				    etiquetas[id_etiqueta].posicion = etiqueta;
				    sprintf(etiquetas[id_etiqueta].nombre,"etiqueta_%d",etiqueta);
				    id_etiqueta++;	  					
					//		
				 }		  
			  }
         }

		 
       } else if (vPolaca[i].tipo==OPERANDO) {
	      // es un valor, constante, voy acumulando en la pila
          vPila.push(vPolaca[i].indTS);
	   }// if de tips
	   
   } // fin for
   

   
   fprintf(archivoASM, "\t ;FIN PROGRAMA \n");
   /*generamos el final */  
   fprintf(archivoASM, "\n\t ;FINALIZACION\n");   
   fprintf(archivoASM, "\t mov AX, 4C00h \n");
   fprintf(archivoASM, "\t int 21h \n");

   /* metos las variables */
   fprintf(archivoASM, "\n.DATA \n\n");
   agregarVariablesTSASM();
   fprintf(archivoASM, "\nEND \n");
	 
   fclose(archivoASM); 
   printf("FIN ASSEMBLER\n");	 
   
}

void agregarVariablesTSASM(){

   // auxiliares
   /*
   fprintf(archivoASM,"aux1 dd ? \n");
   fprintf(archivoASM,"aux2 dd ? \n");
   fprintf(archivoASM,"aux3 dd ? \n");
   */
   fprintf(archivoASM,"\tMAXTEXTSIZE equ 50 \n");
   fprintf(archivoASM,"\t__cadenaAux db 32 dup (?) \n");
   fprintf(archivoASM,"\t__cadenaVacia db 0Dh, 0Ah, \"\", '$', 30 dup(?) \n");
   

    //Recorro la TS y por cada elemento lo declaro en ASSEMBLER
     for(int i=0; i<cant_simbolos; i++)
     {
        switch(tabla_simbolos[i].tipo)
        {
           case REAL:
              fprintf(archivoASM,"\t%s dd ?\n",tabla_simbolos[i].nombre);
           break;
           case INTEGER:
              fprintf(archivoASM,"\t%s dd ?\n",tabla_simbolos[i].nombre);
           break;
           case STRING:
              fprintf(archivoASM,"\t%s db 31 dup(?), '$'\n",tabla_simbolos[i].nombre);
           break;           
           case CTE_REAL:
              fprintf(archivoASM,"\t%s dd %s\n",tabla_simbolos[i].nombre,tabla_simbolos[i].valor);
           break;
           case CTE_INT:
              fprintf(archivoASM,"\t%s dd %s\n",tabla_simbolos[i].nombre,tabla_simbolos[i].valor);
           break;           
           case CTE_STR:
              fprintf(archivoASM,"\t%s db 0Dh, 0Ah, %s, '$', %d dup(?)\n",tabla_simbolos[i].nombre,tabla_simbolos[i].valor,30-tabla_simbolos[i].longitud);
           break;   
           case AUX:
              fprintf(archivoASM,"\t%s dd ?\n",tabla_simbolos[i].nombre);   
           break;           

        }      
     }
}

// tipo POSICION ETIQUETA OPERANDO OPERADOR
void generarPolaca (int valor, int indTS, int tipo) {
   polaca lPolaca;
   
   lPolaca.valor = VACIO;
   lPolaca.tipo = VACIO;
   lPolaca.indTS = VACIO;   
   
   if (valor == INIIF) {
      // guardo para anidamiento
	  vAnidamiento.push(vPolaca.size()); 
   } else if (valor == FINTRUE) {
      // saco el que estaba
	  vPolaca[vAnidamiento.top()].tipo = POSICION;
	  vPolaca[vAnidamiento.top()].valor = vPolaca.size()+1;
	  vAnidamiento.pop();
	  // y agrego el otro que tengo que guardar
	  vAnidamiento.push(vPolaca.size()); 
      //
   } else if (valor == FINFALSE) {
       // aca tengo que llenar algunos vacios del if
	   vPolaca[vAnidamiento.top()-1].tipo = POSICION;
	   vPolaca[vAnidamiento.top()-1].valor = vPolaca.size();
	   vAnidamiento.pop();
	   //
   } else if (valor == INIFOR) {
      // 
      vAnidamiento.push(vPolaca.size()-1); /* donde quedo la posicion del vacio (para el fin de for) */
      vAnidamiento.push(vPolaca.size()-4); /* guardo la posicion del comienzo de la condicion */	
	  //

	  //
      lPolaca.valor = MENORIGUAL; lPolaca.tipo = OPERADOR;
      vPolaca.push_back(lPolaca);
	  
   } else if (valor == FINFOR) {
	     // antes de finalizar, apunto la posicion actual al comienzo de la condicion
		 lPolaca.valor = vAnidamiento.top(); lPolaca.tipo = POSICION; /* guardo donde empieza la condicion para evaluarla */	  
		 vPolaca.push_back(lPolaca);
		 vAnidamiento.pop();

         lPolaca.valor = BI; lPolaca.tipo = OPERADOR;
         vPolaca.push_back(lPolaca);
		 
		 // en la posicion actual de la polaca, es donde tiene que apuntar el fin de la condicion guardado anteriormente
		 vPolaca[vAnidamiento.top()].tipo = POSICION;
		 vPolaca[vAnidamiento.top()].valor = vPolaca.size();
		 vAnidamiento.pop();
		 //
   } else if (valor == FTOC) { // Farenheit to Celsius C = (F -32)/1,8   //POLACA -> expresion 32 - 1.8 / =
		lPolaca.tipo = OPERANDO; lPolaca.indTS = guardarTablaSimbolos("32.0",CTE_REAL,4,CTE); vPolaca.push_back(lPolaca);
		lPolaca.tipo = OPERADOR; lPolaca.valor = RESTA; vPolaca.push_back(lPolaca);
		lPolaca.tipo = OPERANDO; lPolaca.indTS = guardarTablaSimbolos("1.8",CTE_REAL,3,CTE); vPolaca.push_back(lPolaca);
		lPolaca.tipo = OPERADOR; lPolaca.valor = DIVISION; vPolaca.push_back(lPolaca);
   } else if (valor == CTOF) { // Celsius to Farenheit F = C * 1.8 + 32 //POLACA -> expresion 1.8 * 32 + =
        lPolaca.tipo = OPERANDO; lPolaca.indTS = guardarTablaSimbolos("1.8",CTE_REAL,3,CTE); vPolaca.push_back(lPolaca);
		lPolaca.tipo = OPERADOR; lPolaca.valor = MULTIPLIC; vPolaca.push_back(lPolaca);
		lPolaca.tipo = OPERANDO; lPolaca.indTS = guardarTablaSimbolos("32.0",CTE_REAL,4,CTE); vPolaca.push_back(lPolaca);
		lPolaca.tipo = OPERADOR; lPolaca.valor = SUMA; vPolaca.push_back(lPolaca);
   } else if (valor == KTOC) { // Kelvin to Celsius    ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¡ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚ÂºC = ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¡ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚ÂºK - 273,14    //POLACA -> expresion 273.14 - =
        lPolaca.tipo = OPERANDO; lPolaca.indTS = guardarTablaSimbolos("273.14",CTE_REAL,6,CTE); vPolaca.push_back(lPolaca);
		lPolaca.tipo = OPERADOR; lPolaca.valor = RESTA; vPolaca.push_back(lPolaca);		
   } else if (valor == CTOK) { // Celsius to Kelvin    ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¡ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚ÂºK = ÃƒÆ’Ã†â€™ÃƒÂ¢Ã¢â€šÂ¬Ã…Â¡ÃƒÆ’Ã¢â‚¬Å¡Ãƒâ€šÃ‚ÂºC + 273,14    //POLACA -> expresion 273.14 + =
        lPolaca.tipo = OPERANDO; lPolaca.indTS = guardarTablaSimbolos("273.14",CTE_REAL,6,CTE); vPolaca.push_back(lPolaca);
		lPolaca.tipo = OPERADOR; lPolaca.valor = SUMA; vPolaca.push_back(lPolaca);
   } else if ((valor == CTE) || (valor == ID) || (valor == CTE_STR) ) {
        lPolaca.tipo = OPERANDO;
		lPolaca.indTS = indTS;
		vPolaca.push_back(lPolaca);
   } else if (valor==ETIQUETA) {
      lPolaca.tipo = ETIQUETA;
	  lPolaca.valor = vPolaca.size()+1;
      vPolaca.push_back(lPolaca);
   } else {
      lPolaca.tipo = OPERADOR;
	  lPolaca.valor = valor;
      vPolaca.push_back(lPolaca);
   }
}

char * getNombreOperador(int operador){
   switch(operador) {
       case WPRINT:     return "PRINT";
       case OP_ASIG:    return "=";
       case ID:         return "ID";
       case IGUAL:      return "JNE";
       case MENOR:      return "JAE";
       case MENORIGUAL: return "JA";
       case MAYOR:      return "JBE";
       case MAYORIGUAL: return "JB";
       case DISTINTO:   return "JE";
       case CTE:        return "CTE";
       case CTE_STR:    return "CADENA";       
       case DIVISION:   return "/";
       case MULTIPLIC:  return "*";
       case SUMA:       return "+";
       case RESTA:      return "-";
	   case CONCAT:     return "++";
	   case CMP:        return "CMP";
	   case BI:         return "BI";
	   case AND:        return "&&";
	   case OR:         return "||";
	   case NOT:        return "!";
	   default:         return "unnamed";
   }
}

char * getNombreOperadorNegado ( int operador ) {
	switch(operador) {
	   case IGUAL: return "JE";
	   case MENOR: return "JB";
	   case MENORIGUAL: return "JAE";
	   case MAYOR: return "JA";
	   case MAYORIGUAL: return "JBE";
	   case DISTINTO: return "JNE";
	}
}

char * getCodigoOperador(int operador){
   switch(operador) {
      case OP_ASIG:    return "MOV";
      case IGUAL:      return "BNE";
      case MENOR:      return "BGE";
      case MENORIGUAL: return "BGT";
      case MAYOR:      return "BLE";
      case MAYORIGUAL: return "BLT";
      case DISTINTO:   return "BEQ";       
      case DIVISION:   return "FDIV";
      case MULTIPLIC:  return "FMUL";
      case SUMA:       return "FADD";
      case RESTA:      return "FSUB";
	  default:         return "unnamed";
   }
}

void crearArchivoIntermedia(){
   
   if ((archivoPolaca=fopen("intermedia.txt","wt"))==NULL)    {
		  printf("Error, no se encuentra el archivo\n");
		  getch();
		  exit(0);
		}
   //fprintf(archivoPolaca,"%s \n",filename.c_str());
   for (int i=0;i<vPolaca.size();i++){
      if (vPolaca[i].tipo==OPERANDO) {
          fprintf(archivoPolaca,"%s\n",tabla_simbolos[vPolaca[i].indTS].nombre);
      } else if ((vPolaca[i].tipo==ETIQUETA)) {
          fprintf(archivoPolaca,"[%d]\n",vPolaca[i].valor);
	  } else if (vPolaca[i].tipo==POSICION) {	  
	      fprintf(archivoPolaca,"[%d]\n",vPolaca[i].valor);
	  } else {
          fprintf(archivoPolaca,"%s\n",getNombreOperador(vPolaca[i].valor));
      } 	
   }

   fclose(archivoPolaca);	  
}
   
void imprimirFuenteyPolacaPorPantalla(void) {
   FILE *archivoPolaca;
   FILE *codigoFuente;
   char palabra[512];
   char c;
   int i=0;
 
   if ((codigoFuente=fopen("codigoFuente.txt","rt"))==NULL)    {
      printf("Error, no se encuentra el archivo\n");
      getch();
      exit(0);
    } else {
	   printf("\n \n");
	   printf("\n**************************************");
	   printf("\n CodigoFuente: \n");
       while ((c = getc(codigoFuente)) != EOF)
           putchar(c);
	   printf("\n**************************************");
       fclose(codigoFuente);
	}

   if ((archivoPolaca=fopen("intermedia.txt","rt"))==NULL)    {
      printf("Error, no se encuentra el archivo\n");
      getch();
      exit(0);
    } else {
	   printf("\n**************************************");
	   printf("\n Polaca:");
	   printf("\n**************************************\n");	   
       while (fgets(palabra, 512, archivoPolaca) != NULL) {
           printf("[%d] - %s",i,palabra);
		   i++;
	   }
	   printf("[%d] - %s",i,"FIN PROGRAMA");
	   printf("\n**************************************");
       fclose(archivoPolaca);
	}
}
